.. currentmodule:: brian

.. index::
   pair: example usage; gca
   pair: example usage; NeuronGroup
   pair: example usage; run
   pair: example usage; jet
   pair: example usage; xlim
   pair: example usage; show
   pair: example usage; sum
   pair: example usage; axes
   pair: example usage; xticks
   pair: example usage; SpikeMonitor
   pair: example usage; linspace
   pair: example usage; exp
   pair: example usage; yticks
   pair: example usage; close
   pair: example usage; Circle
   pair: example usage; ylim
   pair: example usage; append
   pair: example usage; axis

.. _example-frompapers-computing with neural synchrony-duration selectivity_Fig2A_synchrony_partition:

Example: Fig2A_synchrony_partition (frompapers/computing with neural synchrony/duration selectivity)
====================================================================================================

Brette R (2012). Computing with neural synchrony. PLoS Comp Biol. 8(6): e1002561. doi:10.1371/journal.pcbi.1002561
------------------------------------------------------------------------------------------------------------------
Figure 2A. Synchrony partition for duration selective neurons.

Caption (Fig. 2A)
Decoding synchrony patterns in a heterogeneous
population.
Color represents the latency of the spike produced by each neuron
responding to the stimulus (white if the neuron did not spike). Thus,
neurons with the same color are synchronous for that specific stimulus
(duration). The population can be divided in groups of synchronous
neurons (i.e., with the same color), forming the "synchrony partition".
Circled neurons belong to the same synchronous group.

This script calculates and displays the synchrony partition for one particular duration.
It also saves the results in file, that is required by the script Fig2C_decoding_synchrony.
The synchrony partition is calculated empirically, by simulating the responses of the neurons at
the specific inhibitory duration
and grouping neurons that respond in synchrony (+- 2 ms).

::

    from brian import *
    from numpy.random import seed
    from params import *
    from pylab import cm
    
    # Graphics
    radius=.15
    selected_neuron=7
    # Parameters
    ginh_max=5.
    Nx=5                # number of neurons per row
    N=Nx*Nx             # number of neurons
    rest_time=1*second  # initial time
    duration=500*ms
    delta_t=2*ms        # Size of synchronous groups (maximum time difference)
    
    # Duration-selective neurons
    eqs='''
    dv/dt=(El-v+(gmax*gK+gmax2*gK2+ginh)*(EK-v))/tau : volt
    dgK/dt=(gKinf-gK)/tauK : 1 # IKLT
    dgK2/dt=-gK2/tauK2 : 1 # Delayed rectifier
    gKinf=1./(1+exp((Va-v)/ka)) : 1
    ginh = ginh_max*((t>rest_time) & (t<(rest_time+duration))) : 1
    tauK : ms
    tau : ms
    gmax : 1
    '''
    
    uniform=lambda N:(rand(N)-.5)*2 # uniform between -1 and 1
    seed(31418) # Get the same neurons every time
    
    neurons=NeuronGroup(N,model=eqs,threshold='v>Vt',reset='v=Vr;gK2=1')
    neurons.v=Vr
    neurons.gK=1./(1+exp((Va-El)/ka))
    neurons.tauK=400*ms+uniform(N)*tauK_spread
    alpha=(El-Vt)/(Vt-EK)
    neurons.gmax=alpha*(minx+(maxx-minx)*rand(N))
    neurons.tau=30*ms+uniform(N)*tau_spread
    
    spikes=SpikeMonitor(neurons)
    
    run(rest_time+1.1*second)
    
    # Calculate first spike time of each neuron
    times=zeros(N) # First spike time of each neuron
    times[:]=Inf # Inf means: no response, or response before the start of the stimulus
    blacklist=[] # neurons that fire spontaneously
    for i,t in spikes.spikes:
        if times[i]==Inf:
            times[i]=t-duration-rest_time
            if times[i]<0:
                blacklist.append(i)
    times[blacklist]=Inf
    tmin,tmax=min(times[times!=Inf]),max(times[times!=Inf])
    # Color of each neuron between 0 and 1
    color=(times-tmin)/(tmax+1e-10-tmin) # (to avoid zero division)
    
    # Assign groups; each responding neuron gets a group number
    group_size=delta_t/(tmax-tmin) # size of a group, as a proportion of the timing range
    group_number=array(color/group_size,dtype=int)
    group_number[color==Inf]=-1
    
    # Get the size of each group
    count=zeros(max(group_number)+1) # number of neurons in each group
    for i in range(len(group_number)):
        if group_number[i]!=-1:
            count[group_number[i]]+=1
    
    selected_group=group_number[selected_neuron]
    
    # Display the synchrony partition (Fig. 2A)
    axes(frameon=False)
    axis('scaled')
    xticks([])
    yticks([])
    i=0
    for y in linspace(0,1,Nx):
        for x in linspace(0,1,Nx):
            if color[i]!=Inf:
                if group_number[i]==selected_group:
                    w=4
                    ec="k" # edge color
                else:
                    w=1
                    ec='k'
                cir=Circle((x,y),radius,fc=cm.jet(color[i]),linewidth=w,ec=ec)
            else:
                cir=Circle((x,y),radius,fc='w')
            i+=1
            gca().add_patch(cir)
    xlim(0-2*radius,1+2*radius)
    ylim(0-2*radius,1+2*radius)
    
    # Remove groups with fewer than two neurons and recalculate group numbers
    for i in range(len(group_number)):
        if group_number[i]>=0:
            if count[group_number[i]]>=2:
                group_number[i]=sum(count[:group_number[i]]>=2)
            else:
                group_number[i]=-1
                
    # Save assignment to groups
    f=open('groups'+str(int(duration/ms))+'.txt','w')
    f.write(' '.join([str(x) for x in group_number]))
    f.close()
    
    show()
    

